/**
 * @brief NAND Flash 驱动
 * @author 张勇 / 2020-05-13
 */

#pragma once

#include <stm32f4xx.h>
#include <stm32f4xx_hal_nand.h>
#include "_mcu_gpio.h"
#include "mcu.h"
#include "unidrv/ffsystem.h"

#ifdef __cplusplus
extern "C" {
#endif

//
// NAND 底层驱动
//
/// @brief NAND Flash 驱动数据结构
typedef struct _mcu_nand {
    NAND_HandleTypeDef *nand;
} mcu_nand_t;

uint8_t nand_init(void);
uint8_t nand_modeset(uint8_t mode);
uint32_t nand_readid(void);
uint8_t nand_readstatus(void);
uint8_t nand_wait_for_ready(void);
uint8_t nand_reset(void);
uint8_t nand_waitrb(volatile uint8_t rb);
void nand_delay(volatile uint32_t i);
uint8_t nand_readpage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_read);
uint8_t nand_readpagecomp(uint32_t pagenum, uint16_t colnum, uint32_t cmpval, uint16_t numbyte_to_read, uint16_t *numbyte_equal);
uint8_t nand_writepage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_write_pageconst(uint32_t pagenum, uint16_t colnum, uint32_t cval, uint16_t numbyte_to_write);
uint8_t nand_copypage_withoutwrite(uint32_t source_pagenum, uint32_t dest_pagenum);
uint8_t nand_copypage_withwrite(uint32_t source_pagenum, uint32_t dest_pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_readspare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_read);
uint8_t nand_writespare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_eraseblock(uint32_t blocknum);
void nand_erasechip(void);

uint16_t nand_ecc_get_oe(uint8_t oe, uint32_t eccval);
uint8_t nand_ecc_correction(uint8_t* data_buf, uint32_t eccrd, uint32_t ecccl);

//
// FTL - Flash Translation Layer(闪存转换层) 接口
//
uint8_t ftl_init(void); 
void ftl_badblock_mark(uint32_t blocknum);
uint8_t ftl_check_badblock(uint32_t blocknum); 
uint8_t ftl_used_blockmark(uint32_t blocknum);
uint32_t ftl_find_unused_block(uint32_t sblock, uint8_t flag);
uint32_t ftl_find_same_plane_unused_block(uint32_t sblock);
uint8_t ftl_copy_and_write_to_block(uint32_t source_pagenum, uint16_t colnum, uint8_t *pbuffer, uint32_t numbyte_to_write);
uint16_t ftl_lbn_to_pbn(uint32_t lbnnum); 
uint8_t ftl_write_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount);
uint8_t ftl_read_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount);
uint8_t ftl_create_lut(uint8_t mode);
uint8_t ftl_blockcompare(uint32_t blockx, uint32_t cmpval);
uint32_t ftl_search_badblock(void);
uint8_t ftl_format(void);

//
// 标准 FatFS-Disk-IO APIs
//
DSTATUS ffdisk_nand_init  (ffdisk_t *disk);
DSTATUS ffdisk_nand_status(ffdisk_t *disk);
DRESULT ffdisk_nand_read  (ffdisk_t *disk, BYTE *buff, LBA_t sector, UINT count);
DRESULT ffdisk_nand_write (ffdisk_t *disk, const BYTE *buff, LBA_t sector, UINT count);
DRESULT ffdisk_nand_ioctl (ffdisk_t *disk, BYTE cmd, void *buff);


#ifdef __cplusplus
}
#endif
